/*
 * crt0.o for MIPS r2000/r3000.
 *
 * crt stands for "C runtime".
 *
 * Basically, this is the startup code that gets invoked before main(),
 * and regains control when main returns.
 *
 * All we really do is save a copy of argv for use by the err* and warn*
 * functions, and call exit when main returns.
 */

#include <machine/asmdefs.h>
#include <kern/callno.h>

	.set noreorder	/* so we can use delay slots explicitly */

	.text
	.globl __start
	.type __start,@function
	.ent __start
__start:
	/* Load the "global pointer" register */
	la gp, _gp

   	/*
	 * We expect that the kernel passes argc in a0 and argv in a1.
	 * We do not expect the kernel to set up a complete stack frame,
	 * however.
	 *
	 * The MIPS ABI decrees that every caller will leave 16 bytes of
	 * space in the bottom of its stack frame for writing back the
	 * values of a0-a3, even when calling functions that take fewer
	 * than four arguments. It also requires the stack to be aligned
	 * to an 8-byte boundary. (This is because of 64-bit MIPS, which
	 * we're not dealing with... but we'll conform to the standard.)
	 */
	li t0, 0xfffffff8		/* mask for stack alignment */
	and sp, sp, t0			/* align the stack */
	addiu sp, sp, -16		/* create our frame */

	sw a1, __argv	/* save second arg (argv) in __argv for use later */

	jal main	/* call main */
	nop		/* delay slot */

	/*
	 * Now, we have the return value of main in v0.
	 *
	 * Move it to s0 (which is callee-save) so we still have
	 * it in case exit() returns.
	 *
	 * Also move it to a0 so it's the argument to exit.
	 */
	move s0, v0	/* save return value */
	jal exit	/* call exit() */
	move a0, s0   	/* Set argument (in delay slot) */

	/*
	 * If we got here, something is broken in exit().
	 * Try using _exit().
	 */
	jal _exit	/* Try _exit() */
	move a0, s0	/* Set argument (in delay slot) */

	/*
	 * If *that* doesn't work, try doing an _exit syscall by hand.
	 */
1:
	move a0, s0
	li v0, SYS__exit
	syscall

	/*
	 * ...and if we still can't exit, there's not much we can do
	 * but keep trying.
	 */
	j 1b		/* loop back */
	nop		/* delay slot */
	.end __start
